import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import '../serve/file_serve.dart';

/// 知识图谱节点
class KnowledgeNode {
  final String id;
  final String label;
  final int documentCount;
  final List<String> documents;
  final Color color;
  double x;
  double y;
  double vx = 0;
  double vy = 0;
  bool isDragging = false;

  KnowledgeNode({
    required this.id,
    required this.label,
    required this.documentCount,
    required this.documents,
    required this.color,
    this.x = 0,
    this.y = 0,
  });
}

/// 知识图谱连接
class KnowledgeEdge {
  final String sourceId;
  final String targetId;
  final int strength;
  final List<String> sharedDocuments;

  KnowledgeEdge({
    required this.sourceId,
    required this.targetId,
    required this.strength,
    required this.sharedDocuments,
  });
}

/// 知识图谱组件
class KnowledgeGraphWidget extends StatefulWidget {
  final FileServe fileServe;
  final double width;
  final double height;
  final bool showLabels;
  final bool enableInteraction;
  final Function(KnowledgeNode)? onNodeTap;

  const KnowledgeGraphWidget({
    Key? key,
    required this.fileServe,
    this.width = 300,
    this.height = 200,
    this.showLabels = true,
    this.enableInteraction = true,
    this.onNodeTap,
  }) : super(key: key);

  @override
  _KnowledgeGraphWidgetState createState() => _KnowledgeGraphWidgetState();
}

class _KnowledgeGraphWidgetState extends State<KnowledgeGraphWidget>
    with TickerProviderStateMixin {
  List<KnowledgeNode> nodes = [];
  List<KnowledgeEdge> edges = [];
  bool isLoading = true;
  String? errorMessage;
  late AnimationController _animationController;
  KnowledgeNode? selectedNode;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: Duration(milliseconds: 16),
      vsync: this,
    );
    _loadKnowledgeGraph();
    _startAnimation();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  void _startAnimation() {
    _animationController.repeat();
    _animationController.addListener(() {
      if (mounted) {
        _updatePhysics();
        setState(() {});
      }
    });
  }

  Future<void> _loadKnowledgeGraph() async {
    try {
      setState(() {
        isLoading = true;
        errorMessage = null;
      });

      // 读取tag.json文件
      final tagData = await _loadTagData();
      if (tagData.isEmpty) {
        setState(() {
          isLoading = false;
          errorMessage = '暂无标签数据';
        });
        return;
      }

      // 构建节点和边
      _buildGraphFromTagData(tagData);

      // 初始化节点位置
      _initializeNodePositions();

      setState(() {
        isLoading = false;
      });
    } catch (e) {
      print('KnowledgeGraphWidget: 加载知识图谱失败: $e');
      setState(() {
        isLoading = false;
        errorMessage = '加载失败: $e';
      });
    }
  }

  Future<Map<String, List<String>>> _loadTagData() async {
    try {
      // 使用FileServe的方法获取全局标签数据
      return await widget.fileServe.getGlobalTags();
    } catch (e) {
      print('KnowledgeGraphWidget: 读取标签数据失败: $e');
      return {};
    }
  }

  void _buildGraphFromTagData(Map<String, List<String>> tagData) {
    nodes.clear();
    edges.clear();

    // 创建节点
    final colors = [
      Colors.blue.shade400,
      Colors.green.shade400,
      Colors.orange.shade400,
      Colors.purple.shade400,
      Colors.red.shade400,
      Colors.teal.shade400,
      Colors.indigo.shade400,
      Colors.pink.shade400,
    ];

    int colorIndex = 0;
    for (final entry in tagData.entries) {
      final tag = entry.key;
      final documents = entry.value;
      
      // 过滤掉文档数量太少的标签
      if (documents.length < 1) continue;
      
      nodes.add(KnowledgeNode(
        id: tag,
        label: tag,
        documentCount: documents.length,
        documents: documents,
        color: colors[colorIndex % colors.length],
      ));
      
      colorIndex++;
    }

    // 限制节点数量以提高性能
    if (nodes.length > 20) {
      nodes.sort((a, b) => b.documentCount.compareTo(a.documentCount));
      nodes = nodes.take(20).toList();
    }

    // 创建边（基于共享文档）
    for (int i = 0; i < nodes.length; i++) {
      for (int j = i + 1; j < nodes.length; j++) {
        final node1 = nodes[i];
        final node2 = nodes[j];
        
        // 找到共享的文档
        final sharedDocs = node1.documents
            .where((doc) => node2.documents.contains(doc))
            .toList();
        
        if (sharedDocs.isNotEmpty) {
          edges.add(KnowledgeEdge(
            sourceId: node1.id,
            targetId: node2.id,
            strength: sharedDocs.length,
            sharedDocuments: sharedDocs,
          ));
        }
      }
    }
  }

  void _initializeNodePositions() {
    if (nodes.isEmpty) return;
    
    final random = Random();
    final centerX = widget.width / 2;
    final centerY = widget.height / 2;
    final radius = min(widget.width, widget.height) * 0.3;

    // 确保尺寸有效
    if (widget.width <= 0 || widget.height <= 0) {
      for (final node in nodes) {
        node.x = 150; // 默认位置
        node.y = 100;
        node.vx = 0;
        node.vy = 0;
      }
      return;
    }

    for (int i = 0; i < nodes.length; i++) {
      final angle = (2 * pi * i) / nodes.length;
      final x = centerX + radius * cos(angle) + random.nextDouble() * 20 - 10;
      final y = centerY + radius * sin(angle) + random.nextDouble() * 20 - 10;
      
      // 确保坐标有效
      nodes[i].x = x.isNaN || x.isInfinite ? centerX : x;
      nodes[i].y = y.isNaN || y.isInfinite ? centerY : y;
      nodes[i].vx = 0;
      nodes[i].vy = 0;
    }
  }

  void _updatePhysics() {
    if (nodes.isEmpty) return;

    const double damping = 0.9;
    const double repulsion = 1000;
    const double attraction = 0.1;
    const double centerForce = 0.01;
    const double minDistance = 1.0; // 最小距离，防止除零

    // 重置力
    for (final node in nodes) {
      if (!node.isDragging) {
        // 检查并修复NaN值
        if (node.vx.isNaN || node.vx.isInfinite) node.vx = 0;
        if (node.vy.isNaN || node.vy.isInfinite) node.vy = 0;
        if (node.x.isNaN || node.x.isInfinite) node.x = widget.width / 2;
        if (node.y.isNaN || node.y.isInfinite) node.y = widget.height / 2;
        
        node.vx *= damping;
        node.vy *= damping;
      }
    }

    // 节点间排斥力
    for (int i = 0; i < nodes.length; i++) {
      for (int j = i + 1; j < nodes.length; j++) {
        final node1 = nodes[i];
        final node2 = nodes[j];
        
        final dx = node2.x - node1.x;
        final dy = node2.y - node1.y;
        final distance = max(sqrt(dx * dx + dy * dy), minDistance);
        
        if (distance < 100) {
          final force = repulsion / (distance * distance);
          final fx = (dx / distance) * force;
          final fy = (dy / distance) * force;
          
          // 检查力的有效性
          if (!fx.isNaN && !fx.isInfinite && !fy.isNaN && !fy.isInfinite) {
            if (!node1.isDragging) {
              node1.vx -= fx;
              node1.vy -= fy;
            }
            if (!node2.isDragging) {
              node2.vx += fx;
              node2.vy += fy;
            }
          }
        }
      }
    }

    // 边的吸引力
    for (final edge in edges) {
      try {
        final source = nodes.firstWhere((n) => n.id == edge.sourceId);
        final target = nodes.firstWhere((n) => n.id == edge.targetId);
        
        final dx = target.x - source.x;
        final dy = target.y - source.y;
        final distance = max(sqrt(dx * dx + dy * dy), minDistance);
        
        final force = attraction * edge.strength;
        final fx = (dx / distance) * force;
        final fy = (dy / distance) * force;
        
        // 检查力的有效性
        if (!fx.isNaN && !fx.isInfinite && !fy.isNaN && !fy.isInfinite) {
          if (!source.isDragging) {
            source.vx += fx;
            source.vy += fy;
          }
          if (!target.isDragging) {
            target.vx -= fx;
            target.vy -= fy;
          }
        }
      } catch (e) {
        // 忽略找不到节点的错误
        continue;
      }
    }

    // 中心吸引力
    final centerX = widget.width / 2;
    final centerY = widget.height / 2;
    
    for (final node in nodes) {
      if (!node.isDragging) {
        final dx = centerX - node.x;
        final dy = centerY - node.y;
        
        if (!dx.isNaN && !dx.isInfinite && !dy.isNaN && !dy.isInfinite) {
          node.vx += dx * centerForce;
          node.vy += dy * centerForce;
        }
      }
    }

    // 更新位置
    for (final node in nodes) {
      if (!node.isDragging) {
        // 限制速度
        const double maxVelocity = 5.0;
        node.vx = node.vx.clamp(-maxVelocity, maxVelocity);
        node.vy = node.vy.clamp(-maxVelocity, maxVelocity);
        
        node.x += node.vx;
        node.y += node.vy;
        
        // 边界检查
        final radius = _getNodeRadius(node);
        node.x = node.x.clamp(radius, widget.width - radius);
        node.y = node.y.clamp(radius, widget.height - radius);
        
        // 最终检查，确保坐标有效
        if (node.x.isNaN || node.x.isInfinite) node.x = widget.width / 2;
        if (node.y.isNaN || node.y.isInfinite) node.y = widget.height / 2;
      }
    }
  }

  double _getNodeRadius(KnowledgeNode node) {
    // 增大基础半径，让节点更明显
    return 15 + (node.documentCount * 3).clamp(0, 20).toDouble();
  }

  void _onNodeTap(KnowledgeNode node) {
    setState(() {
      selectedNode = selectedNode == node ? null : node;
    });
    
    if (widget.onNodeTap != null) {
      widget.onNodeTap!(node);
    }
  }

  void _onPanStart(DragStartDetails details, KnowledgeNode node) {
    if (!widget.enableInteraction) return;
    
    setState(() {
      node.isDragging = true;
      selectedNode = node;
    });
  }

  void _onPanUpdate(DragUpdateDetails details, KnowledgeNode node) {
    if (!widget.enableInteraction || !node.isDragging) return;
    
    setState(() {
      node.x += details.delta.dx;
      node.y += details.delta.dy;
      node.vx = 0;
      node.vy = 0;
    });
  }

  void _onPanEnd(DragEndDetails details, KnowledgeNode node) {
    if (!widget.enableInteraction) return;
    
    setState(() {
      node.isDragging = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return Container(
        width: widget.width,
        height: widget.height,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              CircularProgressIndicator(strokeWidth: 2),
              SizedBox(height: 8),
              Text(
                '构建知识图谱中...',
                style: TextStyle(fontSize: 12, color: Colors.grey[600]),
              ),
            ],
          ),
        ),
      );
    }

    if (errorMessage != null) {
      return Container(
        width: widget.width,
        height: widget.height,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(Icons.error_outline, color: Colors.grey[400], size: 32),
              SizedBox(height: 8),
              Text(
                errorMessage!,
                style: TextStyle(fontSize: 12, color: Colors.grey[600]),
                textAlign: TextAlign.center,
              ),
            ],
          ),
        ),
      );
    }

    return Container(
      width: widget.width,
      height: widget.height,
      child: Stack(
        children: [
          // 背景
          Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [
                  Colors.blue.shade50.withOpacity(0.3),
                  Colors.purple.shade50.withOpacity(0.2),
                  Colors.cyan.shade50.withOpacity(0.3),
                ],
              ),
              borderRadius: BorderRadius.circular(12),
            ),
          ),
          
          // 图谱画布
          CustomPaint(
            size: Size(widget.width, widget.height),
            painter: KnowledgeGraphPainter(
              nodes: nodes,
              edges: edges,
              selectedNode: selectedNode,
              showLabels: widget.showLabels,
            ),
          ),
          
          // 交互层
          if (widget.enableInteraction)
            ...nodes.where((node) => 
              !node.x.isNaN && !node.x.isInfinite && 
              !node.y.isNaN && !node.y.isInfinite
            ).map((node) => Positioned(
              left: node.x - _getNodeRadius(node),
              top: node.y - _getNodeRadius(node),
              child: GestureDetector(
                onTap: () => _onNodeTap(node),
                onPanStart: (details) => _onPanStart(details, node),
                onPanUpdate: (details) => _onPanUpdate(details, node),
                onPanEnd: (details) => _onPanEnd(details, node),
                child: Container(
                  width: _getNodeRadius(node) * 2,
                  height: _getNodeRadius(node) * 2,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    color: Colors.transparent,
                  ),
                ),
              ),
            )),
          
          // 节点信息提示
          if (selectedNode != null)
            Positioned(
              left: 8,
              top: 8,
              child: Container(
                padding: EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: Colors.white.withOpacity(0.9),
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.1),
                      blurRadius: 4,
                      offset: Offset(0, 2),
                    ),
                  ],
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text(
                      selectedNode!.label,
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 12,
                      ),
                    ),
                    Text(
                      '${selectedNode!.documentCount} 个文档',
                      style: TextStyle(
                        fontSize: 10,
                        color: Colors.grey[600],
                      ),
                    ),
                  ],
                ),
              ),
            ),
        ],
      ),
    );
  }
}

/// 知识图谱绘制器
class KnowledgeGraphPainter extends CustomPainter {
  final List<KnowledgeNode> nodes;
  final List<KnowledgeEdge> edges;
  final KnowledgeNode? selectedNode;
  final bool showLabels;

  KnowledgeGraphPainter({
    required this.nodes,
    required this.edges,
    this.selectedNode,
    this.showLabels = true,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // 绘制边
    final edgePaint = Paint()
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;

    for (final edge in edges) {
      try {
        final source = nodes.firstWhere((n) => n.id == edge.sourceId);
        final target = nodes.firstWhere((n) => n.id == edge.targetId);
        
        // 检查坐标有效性
        if (source.x.isNaN || source.x.isInfinite || source.y.isNaN || source.y.isInfinite ||
            target.x.isNaN || target.x.isInfinite || target.y.isNaN || target.y.isInfinite) {
          continue;
        }
        
        final opacity = (edge.strength / 5).clamp(0.1, 0.6);
        edgePaint.color = Colors.grey.withOpacity(opacity);
        
        canvas.drawLine(
          Offset(source.x, source.y),
          Offset(target.x, target.y),
          edgePaint,
        );
      } catch (e) {
        // 忽略找不到节点的错误
        continue;
      }
    }

    // 绘制节点
    for (final node in nodes) {
      // 检查坐标有效性
      if (node.x.isNaN || node.x.isInfinite || node.y.isNaN || node.y.isInfinite) {
        continue;
      }
      
      final radius = 15 + (node.documentCount * 3).clamp(0, 20).toDouble();
      final isSelected = selectedNode == node;
      
      // 节点阴影
      final shadowPaint = Paint()
        ..color = Colors.black.withOpacity(0.3)
        ..maskFilter = MaskFilter.blur(BlurStyle.normal, 3);
      
      canvas.drawCircle(
        Offset(node.x + 2, node.y + 2),
        radius,
        shadowPaint,
      );
      
      // 节点主体
      final nodePaint = Paint()
        ..color = isSelected ? node.color : node.color.withOpacity(0.8)
        ..style = PaintingStyle.fill;
      
      canvas.drawCircle(
        Offset(node.x, node.y),
        radius,
        nodePaint,
      );
      
      // 节点边框
      if (isSelected) {
        final borderPaint = Paint()
          ..color = Colors.white
          ..strokeWidth = 2
          ..style = PaintingStyle.stroke;
        
        canvas.drawCircle(
          Offset(node.x, node.y),
          radius,
          borderPaint,
        );
      }
      
      // 节点标签
      if (showLabels) {
        // 对于长标签进行智能缩短
        String displayText = node.label;
        double fontSize = 12;
        
        if (node.label.length > 6) {
          displayText = node.label.substring(0, 5) + '...';
          fontSize = 10;
        } else if (node.label.length > 4) {
          fontSize = 10;
        }
        
        final textPainter = TextPainter(
          text: TextSpan(
            text: displayText,
            style: TextStyle(
              color: Colors.white,
              fontSize: fontSize,
              fontWeight: FontWeight.bold,
              shadows: [
                Shadow(
                  offset: Offset(0.5, 0.5),
                  blurRadius: 1,
                  color: Colors.black.withOpacity(0.5),
                ),
              ],
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        
        textPainter.layout();
        
        final textX = node.x - textPainter.width / 2;
        final textY = node.y - textPainter.height / 2;
        
        // 检查文本位置有效性
        if (!textX.isNaN && !textX.isInfinite && !textY.isNaN && !textY.isInfinite) {
          final textOffset = Offset(textX, textY);
          textPainter.paint(canvas, textOffset);
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
} 